package com.example.myapplication.model.mention;

import android.content.Context;
import android.text.Editable;
import android.text.NoCopySpan;
import android.text.Selection;
import android.util.AttributeSet;
import android.view.KeyEvent;
import android.view.View;
import android.view.inputmethod.EditorInfo;
import android.view.inputmethod.InputConnection;
import android.view.inputmethod.InputConnectionWrapper;
import android.widget.EditText;

import androidx.appcompat.widget.AppCompatEditText;

import com.blankj.utilcode.util.GsonUtils;
import com.example.myapplication.bean.MentionUserEvent;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

/**
 * @好友EditText
 */
public class MentionEditText extends AppCompatEditText {
    KeyEventProxy mKeyEventProxy = new DefaultKeyEventProxy();

    public MentionEditText(Context context) {
        super(context);
    }

    public MentionEditText(Context context, AttributeSet attrs) {
        super(context, attrs);
    }

    public MentionEditText(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
    }

    {
        List<NoCopySpan> watchers = new ArrayList<>();
        watchers.add(new SpanChangedWatcher());
        watchers.add(new AtTextWatcher());
        setEditableFactory(new MentionEditableFactory(watchers));
        setOnKeyListener(new OnKeyListener() {
            @Override
            public boolean onKey(View v, int keyCode, KeyEvent event) {
                return handleKeyEvent(event);
            }
        });
    }

    KeyEventProxy.DeleteCallback mDeleteCallback;

    public void setDeleteCallback(KeyEventProxy.DeleteCallback deleteCallback) {
        mDeleteCallback = deleteCallback;
    }


    private boolean handleKeyEvent(KeyEvent event) {
        return mKeyEventProxy != null && mKeyEventProxy.onKeyEvent(event, getText(), mDeleteCallback);
    }


    @Override
    public InputConnection onCreateInputConnection(EditorInfo outAttrs) {
        return new CustomInputConnectionWrapper(super.onCreateInputConnection(outAttrs), true);
    }


    /**
     * 解决google输入法删除不走OnKeyListener()回调问题
     */
    private class CustomInputConnectionWrapper extends InputConnectionWrapper {


        /**
         * Initializes a wrapper.
         *
         * <p><b>Caveat:</b> Although the system can accept {@code (InputConnection) null} in some
         * places, you cannot emulate such a behavior by non-null {@link InputConnectionWrapper} that
         * has {@code null} in {@code target}.</p>
         *
         * @param target  the {@link InputConnection} to be proxied.
         * @param mutable set {@code true} to protect this object from being reconfigured to target
         *                another {@link InputConnection}.  Note that this is ignored while the target is {@code
         *                null}.
         */
        public CustomInputConnectionWrapper(InputConnection target, boolean mutable) {
            super(target, mutable);
        }


        @Override
        public boolean deleteSurroundingText(int beforeLength, int afterLength) {
            if (beforeLength == 1 && afterLength == 0) {
                return sendKeyEvent(new KeyEvent(KeyEvent.ACTION_DOWN,
                        KeyEvent.KEYCODE_DEL))
                        && sendKeyEvent(new KeyEvent(KeyEvent.ACTION_UP,
                        KeyEvent.KEYCODE_DEL));
            }
            return super.deleteSurroundingText(beforeLength, afterLength);
        }

        @Override
        public boolean sendKeyEvent(KeyEvent event) {
            return (handleKeyEvent(event))
                    || super.sendKeyEvent(event);
        }
    }


    public int insertSpannableString(MentionUser mentionUser) {
        int start = Selection.getSelectionStart(getEditableText());
        int end = Selection.getSelectionEnd(getEditableText());
        if (end < start) {
            int temp = start;
            start = end;
            end = temp;
        }
        mentionUser.setLocaction(start);
        getEditableText().replace(start, end, mentionUser.getSpanableString());
        return start;
    }


    public String getMentionUserJson() {
        if (getText() != null) {
            MentionUser[] integratedSpans = getEditableText().getSpans(0, getText().length(), MentionUser.class);
            List<MentionUserEvent> dataJson = new ArrayList<>();
            StringBuilder stringBuilder = new StringBuilder(getEditableText().toString());
            if (integratedSpans != null && integratedSpans.length > 0) {
                MentionUserEvent userEvent;
                for (MentionUser mentionUser : integratedSpans
                ) {
                    int location = 0;
                    String tag = "@" + mentionUser.getNickname();
                    location = stringBuilder.indexOf(tag);
                    stringBuilder = stringBuilder.delete(location, location + tag.length());
                    userEvent = new MentionUserEvent(mentionUser.getNickname(), mentionUser.getUid(), location);
                    dataJson.add(userEvent);
                }
                return GsonUtils.toJson(dataJson);
            }
        }
        return null;
    }

    public String getPureText() {
        if (getText() != null) {
            String stringBuilder = getEditableText().toString();
            MentionUser[] integratedSpans = getEditableText().getSpans(0, getText().length(), MentionUser.class);
            if (integratedSpans != null && integratedSpans.length > 0) {
                for (MentionUser span : integratedSpans) {
                    if (stringBuilder != null) {
                        stringBuilder = stringBuilder.replace("@" + span.getNickname(), "");
                    }
                }
            }
            return stringBuilder;
        }
        return null;
    }

    public String getContentText() {
        if (getText() != null) {
            String stringBuilder = getEditableText().toString();
            MentionUser[] integratedSpans = getEditableText().getSpans(0, getText().length(), MentionUser.class);
            if (integratedSpans != null && integratedSpans.length > 0) {
                for (MentionUser span : integratedSpans) {
                    if (stringBuilder != null) {
                        stringBuilder = stringBuilder.replace("@" + span.getNickname(), "@" +span.getUid());
                    }
                }
            }
            return stringBuilder;
        }
        return null;
    }

}
